`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 2021/09/15 11:37:32
// Design Name: 
// Module Name: Get_p
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////


module Get_p#(
     parameter DATA_IN_WIDTH      = 24     ,
	 parameter COMPUTE_LEN_WIDTH  = 14     
//	 parameter DATA_OUT_WIDTH     = 24
	 
   )(
   input                        i_clk                    ,
   input                        i_rstn                   ,

 
   input                        i_Data_In_Valid          ,
   input  [2*DATA_IN_WIDTH-1:0] i_Data_In                ,   
   input                        i_Data_In_Last           ,        

   output   signed      [31:0]   psy_data                 ,
   output                        psy_data_valid
//   output  reg  [DATA_OUT_WIDTH-1:0]  o_Phase_Data          ,// //////fra 21bit
//   output  reg                        o_Real_Phase_Last   
   
 
    );

 	reg [DATA_IN_WIDTH-1:0] Data_re ;  //fra 22bit
    reg [DATA_IN_WIDTH-1:0] Data_im ;
     
    

     reg i_data_vld_d1,i_Data_In_Last_d1;
   

     always @(posedge i_clk) begin
         if(~i_rstn) begin
             i_data_vld_d1  <= 0;
         
             i_Data_In_Last_d1<=0;
        
         end
         else begin
             i_data_vld_d1 <= i_Data_In_Valid;
		     Data_re   <= i_Data_In[DATA_IN_WIDTH-1:0] ;
             Data_im   <= i_Data_In[2*DATA_IN_WIDTH-1:DATA_IN_WIDTH] ; 
             i_Data_In_Last_d1<=    i_Data_In_Last;     
         end
  end
  
    
   reg refuse_data_ena;
     always @(posedge i_clk) begin
         if(~i_rstn) begin
             refuse_data_ena  <= 0;
         end
         else if(i_Data_In_Last_d1) begin
             refuse_data_ena <= 1'b1;
         end
  end
  
  
  
  wire  o_i_data_ready;
  wire  [39:0]  o_fft_re,o_fft_im;
  wire  [79:0]  o_fft_data;
//  wire o_fft_data_vld_full;
  wire o_fft_data_vld;
  wire o_fft_data_last;
  

  
  
  wire [9:0] o_fft_data_index;
  
  diffft_8192_b2_v2 diffft_8192_b2_v3_inst (
    .clk(i_clk),                                             
    .rstn(i_rstn),                                                     
//    .din({24'b0,i_real_norm_center}),  
    .din({Data_re,Data_im}),                 
    .din_valid(i_data_vld_d1&~refuse_data_ena),                    
    .din_ready(o_i_data_ready),                
    .din_last(i_Data_In_Last_d1),  
                
    .dout(o_fft_data),      //21bit fra                 
    .dout_valid(o_fft_data_vld),        
    .dout_last(o_fft_data_last),                
    .error()  
  );
  
//fft_amp fft_amp1_inst (
//    .aclk(i_clk),                                                // input wire aclk
//    .aresetn(i_rstn),                                          // input wire aresetn
//    .s_axis_config_tdata({8'h01,3'd0,5'b01101}),                  // input wire [15 : 0] s_axis_config_tdata
//    .s_axis_config_tvalid(1'b1),                // input wire s_axis_config_tvalid
//    .s_axis_config_tready(),                // output wire s_axis_config_tready
//    .s_axis_data_tdata({Data_im,Data_re}),                      // input wire [31 : 0] s_axis_data_tdata
//    .s_axis_data_tvalid(i_data_vld_d1),                    // input wire s_axis_data_tvalid
//    .s_axis_data_tready(o_i_data_ready),                    // output wire s_axis_data_tready
//    .s_axis_data_tlast(i_Data_In_Last_d1),                      // input wire s_axis_data_tlast
//    .m_axis_data_tdata(o_fft_data),                      // output wire [63 : 0] m_axis_data_tdata
//    .m_axis_data_tuser(o_fft_data_index),                      // output wire [15 : 0] m_axis_data_tuser
//    .m_axis_data_tvalid(o_fft_data_vld),                    // output wire m_axis_data_tvalid
//    .m_axis_data_tready(1'b1),                    // input wire m_axis_data_tready
//    .m_axis_data_tlast(o_fft_data_last),                      // output wire m_axis_data_tlast
//    .event_frame_started(),                  // output wire event_frame_started
//    .event_tlast_unexpected(),            // output wire event_tlast_unexpected
//    .event_tlast_missing(),                  // output wire event_tlast_missing
//    .event_status_channel_halt(),      // output wire event_status_channel_halt
//    .event_data_in_channel_halt(),    // output wire event_data_in_channel_halt
//    .event_data_out_channel_halt()  // output wire event_data_out_channel_halt
//  );
    
  assign o_fft_re = o_fft_data[39:0];
  assign o_fft_im = o_fft_data[79:40];
  
  wire signed [23:0]  o_fft_re_cut,o_fft_im_cut;
  assign o_fft_re_cut = o_fft_re[32:9]; //10bit int  13bit fra
  assign o_fft_im_cut = o_fft_im[32:9];
  
 wire  [23:0]  o_module_data;   
 wire  o_module_data_valid;
    cordic_myself_v3 #(
	     .DIN_WIDTH      (  DATA_IN_WIDTH ) )
	    
   cordic_myself2_inst (
      .clk(i_clk),      // input wire clk
      .rst_n(i_rstn),
      .x(o_fft_re_cut),      
      .y(o_fft_im_cut),  
      .start(o_fft_data_vld),  
      .angle(),  
      .length(o_module_data),
      .finished(o_module_data_valid)
    );  
    
//                   integer fp8;
//                   integer i;
//                   initial begin
                 
//           fp8 = $fopen("o_module_data_24bitd.txt");

//                     i=0;
//                     end
//            always @(posedge i_clk) begin
//                      if(i>=8192) begin
//                          $fclose(fp8);
//                     end
//                       else if(o_module_data_valid) begin
//                          i <= i+1;
//                          $fdisplay(fp8,"%d",o_module_data);
//                       end
//                   end  
    
    
    
    reg    [35:0] PU,PL,PU_hold;                                        ////////  24+log2(8192)=36
    reg     sum_PU_rst,sum_PU_valid, sum_PL_rst,sum_PL_valid;
//    wire   [DATA_IN_WIDTH-1:0] o_real_data;
//    wire  o_real_data_valid;
//    reg  sum_r_vld;
    
//    wire   [DATA_IN_WIDTH-1:0] o_sum_r;
//    reg    [DATA_IN_WIDTH-1:0] Sum_hold;
//    wire  o_real_data_last;   
    
    
    
   reg [13-1:0] addr_cnt;
    always @(posedge i_clk) begin
            if(~i_rstn) addr_cnt <= 10'b0;
            else if(o_module_data_valid && (addr_cnt==13'd8191)) addr_cnt <= 10'b0;
            else if(o_module_data_valid) addr_cnt <= addr_cnt + 1;
            else addr_cnt <= addr_cnt;
        end
        
        
     	always @ (posedge i_clk)
            if(i_rstn==1'b0)
		     begin
              sum_PU_rst   <=  'd0 ;
              sum_PU_valid <=   0;
              sum_PL_rst <=   0;
              sum_PL_valid <=   0;
             end	
             else  begin    
		      sum_PU_rst   <=(addr_cnt==13'd4095);
              sum_PU_valid <=(addr_cnt==13'd4095);
              sum_PL_rst   <=(addr_cnt==13'd8191); 
              sum_PL_valid <= (addr_cnt==13'd8191); 	      
		      end      
//   assign  sum_PU_rst=(addr_cnt==13'd4095);  
//   assign  sum_PU_valid=(addr_cnt==13'd4095); 
//   assign  sum_PL_rst=(addr_cnt==13'd8191);  
//   assign  sum_PL_valid=(addr_cnt==13'd8191); 

     always @(posedge i_clk) begin
        if(sum_PU_rst||~i_rstn) PU <= 0;
        else if(o_module_data_valid && (addr_cnt<=13'd4095)) PU <= PU + o_module_data;
//        else if(o_module_data_valid) PU <= PU + o_module_data;
        else PU <= PU;
    end 
    
    always @(posedge i_clk) begin
        if(sum_PU_rst||~i_rstn) PL <= 0;
//        else if(o_module_data_valid && (addr_cnt>=13'd4096)) PL <= PL + o_module_data;
        else if(o_module_data_valid && (addr_cnt>=13'd4096)) PL <= PL + o_module_data;
        else PL <= PL;
    end 
    
   	always @ (posedge i_clk)
            if(i_rstn==1'b0)
		     begin
              PU_hold   <=  'd0 ;
             end	
             else if(sum_PU_valid) 
              begin  PU_hold   <= PU ;
		      end
		      else begin    
		      PU_hold   <=PU_hold;
		      end 
		      
  wire signed [35:0] psy_numerator;
  wire signed [35:0] psy_numerator_unsign;
  wire sign_flag;
  reg  sign_flag_hold;
//  wire signed [71:0] psy_numerator_expand;
  wire [35:0] psy_denominator;
  assign psy_numerator=PL-PU_hold;
  assign psy_denominator=PL+PU_hold;
  
  assign  psy_numerator_unsign=(psy_numerator>0)?psy_numerator:(-psy_numerator);
  assign  sign_flag=(psy_numerator>0)?0:1;
  
     	always @ (posedge i_clk)
            if(i_rstn==1'b0)
		     begin
              sign_flag_hold   <=  'd0 ;
             end	
             else if(sum_PL_valid) 
              begin  sign_flag_hold   <= sign_flag ;
		      end
		      else begin    
		      sign_flag_hold   <=sign_flag_hold;
		      end 
  
  
  
  
  wire  signed [71:0] PSY;
  wire  PSY_valid;
    divider_myself_sign #(
	     .N          (  72  ) ,
	     .M          (  36  ) ,
	     .N_ACT      (  107  )
	     ) 
    divider_myself_inst (
      .clk(i_clk),                      // input wire clk
      .rstn(i_rstn),
      .data_rdy(sum_PL_valid),      // 
      .dividend({psy_numerator_unsign,36'b0}),        //
      .divisor(psy_denominator),                  // 
      .res_rdy(PSY_valid),            // 
      .merchant(PSY),           // output wire full
      .remainder()    
    ); 
  wire signed [71:0] psy_sign; 
  assign  psy_sign=(sign_flag_hold>0)?-PSY:PSY;  
   
   assign psy_data=psy_sign[40:9];// 4bit int 27bit fra
    assign psy_data_valid= PSY_valid;
    
    
endmodule